package com.caocaog.market.service.impl;

import com.caocaog.market.entity.GoodsSpec;
import com.caocaog.market.mapper.GoodsSpecMapper;
import com.caocaog.market.service.GoodsSpecService;
import com.caocaog.market.vo.GoodsAttributeVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.base.entity.FieldRedisItem;
import org.jeecg.common.system.base.service.impl.GenericServiceImpl;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 商品规格
 *
 * @author chechen
 * @date 2022-04-11
 */
@Slf4j
@Service
public class GoodsSpecServiceImpl extends GenericServiceImpl<GoodsSpecMapper, GoodsSpec> implements GoodsSpecService {


    @Override
    public List<GoodsAttributeVo> getGoodsSpecDataByGoodsId(String goodsId) {
        return super.selectListByFieldCache(goodsId, CacheConstant.GOODS_SPEC_LIST_BY_GOODS_ID).stream()
                .map(spec -> GoodsAttributeVo.builder()
                        .id(spec.getId())
                        .key(spec.getId())
                        .editable(Boolean.FALSE)
                        .nameSku(spec.getName())
                        .packFeeSku(spec.getPackFee())
                        // .pictureSku(spec.getPicture())
                        .priceSku(spec.getPrice())
                        .stockSku(spec.getStock())
                        .weightSku(spec.getWeight())
                        .weightGSku(spec.getWeightG())
                        .build())
                .collect(Collectors.toList());
    }


    @Override
    public GoodsSpec getGoodsSpec(String id) {
        return super.getByIdCache(id);
    }


    @Override
    public List<GoodsSpec> getGoodsSpecByGoodsId(String goodsId) {
        return super.selectListByFieldCache(goodsId, CacheConstant.GOODS_SPEC_LIST_BY_GOODS_ID);
    }


    /**
     * 插入更新商品规格时到预处理
     */
    public void preprocess(GoodsSpec goodsSpec) {
        /* 重量 g -> kg 转换， g的优先级比kg高，只有g为null时，才会用kg转g。
        g / 1000 = kg 除的时候四舍五入，保留小数点后三位（基本不可能会出现小数点后四位的情况发生）。
        kg * 1000 = g */
        BigDecimal thousand = new BigDecimal("1000");
        if (goodsSpec.getWeightG() != null) {
            goodsSpec.setWeight(new BigDecimal(goodsSpec.getWeightG()).divide(thousand, 3, RoundingMode.HALF_UP).stripTrailingZeros().toString());
        } else if (StringUtils.isNotBlank(goodsSpec.getWeight())) {
            goodsSpec.setWeightG(new BigDecimal(goodsSpec.getWeight()).multiply(thousand).intValue());
        }
    }


    @Override
    public GoodsSpec insertGoodsSpec(GoodsSpec goodsSpec) {
        this.preprocess(goodsSpec);

        int insertRecordCount = super.insertCache(goodsSpec);
        if (insertRecordCount == 0) {
            throw new JeecgBootException("插入商品规格失败, entity-> " + goodsSpec);
        }
        return super.getByIdCache(goodsSpec.getId());
    }


    @Override
    public GoodsSpec updateGoodsSpec(GoodsSpec goodsSpec) {
        this.preprocess(goodsSpec);

        int updateRecordCount = super.updateCache(goodsSpec);
        if (updateRecordCount == 0) {
            throw new JeecgBootException("更新商品规格失败, entity-> " + goodsSpec);
        }
        return super.getByIdCache(goodsSpec.getId());
    }


    @Override
    public int insertBatchGoodsSpec(List<GoodsSpec> goodsSpecs) {
        goodsSpecs.forEach(this::preprocess);
        int insertBatchRecordCount = super.insertBatchCache(goodsSpecs);
        if (insertBatchRecordCount == 0) {
            goodsSpecs.forEach(goodsAttrsError -> log.error(goodsAttrsError.toString()));
            throw new JeecgBootException("插入商品规格失败, list-^");
        } else if (insertBatchRecordCount < goodsSpecs.size()) {
            goodsSpecs.forEach(goodsAttrsError -> log.info(goodsAttrsError.toString()));
            throw new JeecgBootException("没有全部成功插入规格属性, list-^");
        }
        return insertBatchRecordCount;
    }


    @Override
    public int updateBatchGoodsSpec(List<GoodsSpec> goodsSpecs) {
        goodsSpecs.forEach(this::preprocess);
        int updateBatchRecordCount = super.updateBatchCache(goodsSpecs);
        if (updateBatchRecordCount == 0) {
            goodsSpecs.forEach(goodsAttrsError -> log.error(goodsAttrsError.toString()));
            throw new JeecgBootException("更新商品规格失败, list-^");
        } else if (updateBatchRecordCount < goodsSpecs.size()) {
            goodsSpecs.forEach(goodsAttrsError -> log.info(goodsAttrsError.toString()));
            throw new JeecgBootException("没有全部成功更新商品规格, list-^");
        }
        return updateBatchRecordCount;
    }


    @Override
    public int deleteGoodsSpecByGoodsId(String goodsId) {
        return super.deleteByEntityListAllCache(selectListByFieldCache(goodsId, CacheConstant.GOODS_SPEC_LIST_BY_GOODS_ID));
    }


    @Override
    public String[] getGoodsSpecIdsByGoodsIds(String... goodsIds) {
        return Arrays.stream(goodsIds)
                .distinct()
                .map(goodsId -> this.selectListByFieldCache(goodsId, CacheConstant.GOODS_SPEC_LIST_BY_GOODS_ID))
                .flatMap(Collection::stream)
                .map(GoodsSpec::getId)
                .toArray(String[]::new);
    }


    @Override
    public String getName() {
        return "商品规格";
    }

    @Override
    public List<FieldRedisItem<GoodsSpec>> getAllFieldCacheList() {
        return Arrays.asList(
                FieldRedisItem.build(GoodsSpec::getId, CacheConstant.GOODS_SPEC_INFO, true),
                FieldRedisItem.build(GoodsSpec::getGoodsId, CacheConstant.GOODS_SPEC_LIST_BY_GOODS_ID)
        );
    }

}
